package com.mtao.security;


import com.fasterxml.jackson.databind.ObjectMapper;
import com.mtao.constant.SecurityConstants;
import com.mtao.exception.BadRequestException;
import com.mtao.utils.JwtUtils;
import com.mtao.utils.StringUtil;
import com.mtao.utils.ThreadLocalUtil;
import com.mtao.mapper.SysUserMapper;
import com.mtao.entity.SysUser;
import io.jsonwebtoken.Claims;
import io.micrometer.common.util.StringUtils;
import jakarta.annotation.Resource;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.NonNull;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;

/**
 * @program: ems-admin-boot
 * @description: this is a class
 * @author: starao
 * @create: 2021-11-27 13:15
 **/
@Component
public class JwtAuthorizationFilter extends OncePerRequestFilter {

    @Resource
    private JwtUtils jwtUtils;

    @Resource
    private SysUserMapper sysUserMapper;

    /**
     * @Description: 过滤用户请求
     * @Param: [request, response, filterChain]
     * @return: void
     * @Author: starao
     * @Date: 2021/11/27
     */
    @Override
    protected void doFilterInternal(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response,
                                    @NonNull FilterChain filterChain) throws ServletException, IOException {
        response.setContentType("application/json;charset=utf-8");
        try {
            //  从request中获取token
            String token = this.getTokenFromHttpServletRequest(request);
//            if (!jwtUtils.verifyToken(token)) {
//                throw new BadRequestException("token过期");
//            }
            //  如果token不存在或者携带了刷新token(长度小于150,可以根据自己生成的refreshToken来判断),
            //  直接放行,由系统Security判断是否具有访问权限
            if (StringUtil.isBlank(token) || token.length() < 150) {
                filterChain.doFilter(request, response);
                return;
            }
            Claims claims = jwtUtils.getClaimsByToken(token);
            String name = (String) claims.get("userName");
            SysUser user = sysUserMapper.fimdName(name);
            if (user == null) {
                PrintWriter writer = response.getWriter();
                HashMap<String, Object> map = new HashMap<>();
                map.put("code", 401);
                map.put("msg", "用户不存在");
                ObjectMapper objectMapper = new ObjectMapper();
                String json = objectMapper.writeValueAsString(map);
                writer.write(String.valueOf(json));
                writer.flush();
                writer.close();
                filterChain.doFilter(request, response);
                return;
            }
            if (!user.getEnabled()) {
                PrintWriter writer = response.getWriter();
                HashMap<String, Object> map = new HashMap<>();
                map.put("code", 401);
                map.put("msg", "用户已被禁用");
                ObjectMapper objectMapper = new ObjectMapper();
                String json = objectMapper.writeValueAsString(map);
                writer.write(String.valueOf(json));
                writer.flush();
                writer.close();
                filterChain.doFilter(request, response);
                return;
            }
            //  校验token是否有效
            if (jwtUtils.verifyToken(token)) {
                ThreadLocalUtil.set(claims);
                //  获取认证信息
                Authentication authentication = jwtUtils.getAuthentication(token);
                //  将认证信息保存在spring安全上下文中
                SecurityContextHolder.getContext().setAuthentication(authentication);
                filterChain.doFilter(request, response);
                ThreadLocalUtil.remove();
            }
        } catch (BadRequestException e) {
            //  token问题,统一作401处理
            response.setStatus(HttpStatus.UNAUTHORIZED.value());
        }
    }


    /**
     * @Description: 从http中获取token
     * @Param: [request]
     * @return: java.lang.String
     * @Author: starao
     * @Date: 2021/11/27
     */
    private String getTokenFromHttpServletRequest(HttpServletRequest request) {
        //  通过Authorization获取token
        String authorization = request.getHeader(SecurityConstants.TOKEN_HEADER);
        if (StringUtils.isNotBlank(authorization) && authorization.startsWith(SecurityConstants.TOKEN_PREFIX)) {
            return authorization.replace(SecurityConstants.TOKEN_PREFIX, "");
        }
        return null;
    }

}
